package ua.pp.parkee;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * Created by parkee on 27.07.14.
 */
public class MyClassLoader extends ClassLoader {

    public static final String BASE_DIR = System.getProperty("user.dir");
    public static final String SRC_DIR = "/src/main/java";
    public static final String TARGET_DIR = "/target/classes";
    //public static final String ALLOWED_PACKAGE = "ua.pp.parkee";

    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {

        //if(!name.startsWith(ALLOWED_PACKAGE))
        //    return super.loadClass(name);

        Path srcPath = getSourcePath(name);
        Path targetPath = getTargetPath(name);

        try {
            compile(srcPath);
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }

        try {
            byte[] bytes = Files.readAllBytes(targetPath);
            if (bytes != null) {
                return defineClass(name, bytes, 0, bytes.length);
            }
        } catch (IOException e) {
            return super.loadClass(name);
            //e.printStackTrace();
        }

        return null;
    }

    public static Path getTargetPath(String fullyQualifiedName) {
        String s = packageToPath(fullyQualifiedName);
        String path = String.format("%s%s/%s.class", BASE_DIR, TARGET_DIR, s);
        return Paths.get(path);
    }

    public static Path getSourcePath(String fullyQualifiedName) {
        String s = packageToPath(fullyQualifiedName);
        String path = String.format("%s%s/%s.java", BASE_DIR, SRC_DIR, s);
        return Paths.get(path);
    }

    private static String packageToPath(String name) {
        return name.replaceAll("\\.", "/");
    }

    private void compile(Path srcPath) throws InterruptedException, IOException {
        Runtime.getRuntime().exec(new String[]{
                "javac",
                "-d", BASE_DIR + TARGET_DIR,
                srcPath.toString()
        }).waitFor();
    }
}
